﻿using FluentValidation;
using FluentValidation.Results;
using QAS.Nekorama.Common;
using Resources;
using System;
using System.Linq;

namespace QAS.Nekorama.Models
{
    /// <summary>
    /// カスタム妥当
    /// </summary>
    public class CustomValidators
    {
        /// <summary>
        /// 回答の妥当
        /// </summary>
        public class AnswerValidator : AbstractValidator<Answer>
        {
            /// <summary>
            /// 回答の妥当
            /// </summary>
            public AnswerValidator()
            {
                RuleFor(a => a.Content).NotEmpty().WithMessage(Messages.CONTENT_REQUIRED);
                //RuleFor(a => a.Content.Trim().Length).GreaterThan(30).WithMessage(Messages.ANSWER_CONTENT_LENGTH);
                Custom(a => Helper.Html2Text(a.Content).Trim().Length < Constants.ASWER_CONTENT_MINIMUM ? new ValidationFailure("Content", Messages.ANSWER_CONTENT_LENGTH) : null);
            }
        }

        /// <summary>
        /// 報奨の妥当
        /// </summary>
        public class BountyValidator : AbstractValidator<Bounty>
        {
            /// <summary>
            /// 報奨の妥当
            /// </summary>
            public BountyValidator()
            {
                RuleFor(b => b.Amount).NotNull().NotEmpty().WithMessage(Messages.BOUNTY_NOT_EMPTY);
                RuleFor(b => b.Amount).InclusiveBetween(100, 1000).WithMessage(Messages.BOUNTY_RANGE);

                //現在なユーザーの評価点をチェックします。
                Custom(b =>
                       {
                           using (var db = new Entities())
                           {
                               User user = db.Users.Find(b.CreatedUser);
                               return b.Amount >= user.Reputation
                                   ? new ValidationFailure("Amount", Messages.NOT_ENOUGH_PERMISSION)
                                   : null;
                           }
                       });

                //報奨は存在したかどうかちぇっくします。
                Custom(b =>
                       {
                           try
                           {
                               using (var db = new Entities())
                               {
                                   Bounty existingbounty = db.Bounties.SingleOrDefault(x => x.QuestionID == b.QuestionID);
                                   return existingbounty == null
                                       ? null
                                       : new ValidationFailure("BountyId",
                                           Resources.Messages.BOUNTY_ALREADY_ATTACHED);
                               }
                           }
                           catch (Exception)
                           {
                               return new ValidationFailure("BountyId", Resources.Messages.BOUNTY_ALREADY_ATTACHED);
                           }
                       });
            }
        }

        /// <summary>
        /// コンメントの妥当
        /// </summary>
        public class CommentValidator : AbstractValidator<Comment>
        {
            /// <summary>
            /// コンメントの妥当
            /// </summary>
            public CommentValidator()
            {
                RuleFor(a => a.Content).NotEmpty().WithMessage(Messages.CONTENT_REQUIRED);
                RuleFor(a => a.Content.Trim().Length).GreaterThan(20).WithMessage(Messages.COMMENT_LENGTH);
            }
        }

        /// <summary>
        /// 外部ログインの妥当
        /// </summary>
        public class ExternalLoginValidator : AbstractValidator<RegisterExternalLoginModel>
        {
            /// <summary>
            /// 外部ログインの妥当
            /// </summary>
            public ExternalLoginValidator()
            {
                Custom(u =>
                {
                    if (string.IsNullOrEmpty(u.DisplayName) || u.DisplayName.Trim().Length > 10 || u.DisplayName.Trim().Length < 3)
                    {
                        return new ValidationFailure("DisplayName", Resources.Messages.DISPLAY_NAME_RANGE);
                    }

                    return null;
                });
                //RuleFor(u => u.DisplayName).NotEmpty().WithLocalizedMessage(() => Messages.DISPLAY_NAME_RANGE);
                //RuleFor(u => u.DisplayName).Length(3, 10).WithLocalizedMessage(() => Messages.DISPLAY_NAME_RANGE);
                RuleFor(u => u.DisplayName).Matches(@"^[^`~!@#\$%\^&\*()\-_=\+\[\{}\|;',\\\.<>/\]\?:‘～！＠＃＄％＾＆＊（）－＿＝＋「｛」｝￥｜；：’”、＜。＞・？\""]+$").WithLocalizedMessage(() => Messages.DISPLAY_NAME_CHARACTER_LIMIT);
                RuleFor(u => u.DisplayName)
                    .Must(UniqueName)
                    .WithLocalizedMessage(() => Messages.DISPLAY_NAME_CHOSEN);
            }

            /// <summary>
            /// 表示名はユニークかどうかチェックします。
            /// </summary>
            /// <param name="name">表示名</param>
            /// <returns>ユニークかどうか</returns>
            private bool UniqueName(string name)
            {
                var db = new Entities();
                User displayname = db.Users.SingleOrDefault(u => u.DisplayName == name.Trim());

                return displayname == null;
            }
        }
    }
}